package com.joey.concurrency.example.threadPool;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author hyy
 * @description
 * @date 2019-03-20 9:29
 **/
@Slf4j
public class CustomThreadPoolExecutor {

    private ThreadPoolExecutor threadPoolExecutor = null;

    public void init(){
        threadPoolExecutor = new ThreadPoolExecutor(
                4,
                2 * 4 + 1,
                30,
                TimeUnit.MINUTES,
                new ArrayBlockingQueue<Runnable>(10),
                new CustomizableThreadFactory());
    }

    public void destroy(){
        if(threadPoolExecutor != null){
            threadPoolExecutor.shutdownNow();
        }
    }

    public ExecutorService getCustomThreadPoolExecutor(){
        return this.threadPoolExecutor;
    }

    private class CustomThreadFactory implements ThreadFactory {

        private AtomicInteger atomicInteger = new AtomicInteger(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            String threadName = CustomThreadPoolExecutor.class.getSimpleName()
                    + atomicInteger.addAndGet(1);
            log.info("threadName : {}",threadName);
            t.setName(threadName);
            return t;
        }
    }

    private class CustomRejectedExecutionHandler implements RejectedExecutionHandler{

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            log.info("记录异常!");
        }
    }

    public static void main(String[] args) {
        //构造缓冲功能线程池，配置corePoolSize=0,maximumPoolSize=Integer.MAX_VALUE,
        //keepAliveTime=60s,以及一个无容量的阻塞队列SynchronousQueue,因此任务提交之后，
        //将会创建新线程执行，空闲线程超过60s将会销毁。
        /**
         * 经典的生产者-消费者模式，操作流程是这样的：
         * 有多个生产者，可以并发生产产品，把产品置入队列中，如果队列满了，生产者就会阻塞；
         * 有多个消费者，并发从队列中获取产品，如果队列空了，消费者就会阻塞；
         */
        ExecutorService executorService1 = Executors.newCachedThreadPool();

        //构造一个固定线程数目的线程池，配置的corePoolSize与maximumPoolSize大小相同，
        //同时使用了一个无界LinkedBlockingQueue存放阻塞任务，因此多余的任务将存在阻塞队列，
        //不会由RejectedExecutionHandler
        ExecutorService executorService2 = Executors.newFixedThreadPool(20);

        //构造一个只支持一个线程的线程池，配置corePoolSize=maximumPoolSize=1,无界阻塞
        //队列，LinkedBlockingQueue保证任务由一个线程串行执行。
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();

        //构造有定时功能的线程池，配置corePoolSize,无界延迟阻塞队列DelayedWorkQueue,
        //有意思的是maximumPoolSize=Integer.MAX_VALUE,由于DelayedWorkQueue是无界队列，所以
        //这个值没有意义
        ExecutorService executorService4 = Executors.newScheduledThreadPool(9);


        CustomThreadPoolExecutor customThreadPoolExecutor = new CustomThreadPoolExecutor();
        //初始化
        customThreadPoolExecutor.init();
        ExecutorService executorService = customThreadPoolExecutor.getCustomThreadPoolExecutor();
        for (int i = 0; i < 100; i++) {
            log.info("提交第{}个任务",i);
            try{
                Thread.sleep(1000);
            }catch (Exception e){
                log.error("Exception",e);
            }
            executorService.execute(() -> {

                log.info("running ......");
            });
        }

        customThreadPoolExecutor.destroy();

        try{
            Thread.sleep(1000);
        }catch (Exception e){
            log.error("Exception",e);
        }

    }


}




    